import fetch from "node-fetch"
import puppeteer from "../../lib/puppeteer/puppeteer.js"

const voiceAPI = "https://yuyin.3198550236.fun/"
const charactersAPI = voiceAPI + "characters"
const image = ""
// 使用Map优化角色查找性能
let roleData = {}
let characterMap = new Map()

loadCharacterList()

export class Voice extends plugin {
  constructor() {
    super({
      name: "喵语音合成",
      dsc: "语音合成",
      event: "message",
      priority: -5000,
      rule: [
        {
          reg: "^#(.+)说.+",
          fnc: "Voice"
        },
        {
          reg: "^#?语音(合成)?(角色)?列表$",
          fnc: "VoiceList"
        },
        {
          reg: "^#?(刷新|更新)语音(合成)?(角色)?列表$",
          fnc: "Update"
        }
      ]
    })
  }

  async Voice(e) {
    // 使用更严谨的正则匹配
    const matchResult = e.msg.match(/^#(.+?)说(快|慢)?(\d\.\d)?\s*([\S\s]+)$/)
    if (!matchResult) return

    let [, speaker, speedType, speedValue, text] = matchResult
    speaker = speaker.trim()

    // 处理语速参数
    let speed = 1.0
    if (speedValue) {
      speed = parseFloat(speedValue)
      if (speedType === "慢") speed = 1.0 - speed / 2
      if (speedType === "快") speed = 1.0 + speed
      speed = Math.min(Math.max(speed, 0.5), 2.0)
    }

    // 使用缓存提高查找效率
    const character = characterMap.get(speaker)
    if (character) {
      try {
        const url = new URL(voiceAPI + "tts")
        url.searchParams.append("character", character.id)
        url.searchParams.append("text", text.replace(/[\n\r]/g, " "))
        url.searchParams.append("speed", speed.toFixed(1))

        logger.mark("合成请求URL:", url.toString())
        await this.reply(segment.record(url.toString()))
      } catch (err) {
        logger.error("语音合成失败:", err)
        e.reply("语音合成失败，请稍后再试")
      }
    }
  }

  async VoiceList(e) {
    if (characterMap.size === 0) {
      await loadCharacterList()
    }

    if (!puppeteer.browser) {
    }
    let renderData = {
      ResPath: process.cwd().replace(/\\/g, "/") + "/plugins/miao-plugin/resources/common/font/",
      quality: 100,
      list: roleData,
      url: image
    }
    if (!puppeteer.browser) {
      await puppeteer.browserInit()
    }
    let page
    try {
      page = await puppeteer.browser.newPage()
      await page.setContent(getHtml(renderData))
      const body = (await page.$("#container")) || (await page.$("body"))
      const base64 = await body.screenshot({
        encoding: "base64",
        type: "jpeg"
      })
      page.close().catch((err) => logger.error(err))
      e.reply(segment.image(`base64://${base64}`))
    } catch (error) {
      logger.error(error)
      if (page) {
        page.close().catch((err) => logger.error(err))
      }
      e.reply("渲染失败")
    }
  }

  async Update(e) {
    await loadCharacterList()
    e.reply(`语音列表刷新完成，当前共加载${characterMap.size}个角色`)
  }
}

async function loadCharacterList() {
  try {
    const response = await fetch(charactersAPI)
    if (!response.ok) throw new Error(`HTTP ${response.status}`)

    roleData = await response.json()
    characterMap.clear()

    // 建立角色名称索引
    for (const type of Object.values(roleData)) {
      for (const role of type) {
        for (const name of role.names) {
          characterMap.set(name, role)
        }
      }
    }
    logger.mark("角色列表加载完成，总角色数:", characterMap.size)
  } catch (err) {
    logger.error("加载角色列表失败:", err)
    throw err
  }
}

/**
 *
 * @param {{
 *  account: string,
 *  totalRecords: number,
 *  msgList: Array,
 *  ResPath: string,
 *  quality: number
 * }} data
 * @returns
 */
function getHtml(data) {
  return `<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>角色语音分类列表</title>
  <style>

    @font-face {
      font-family: "YS";
      src: url("${data.ResPath}HYWH-65W.ttf");
      font-weight: normal;
      font-style: normal;
    }
    body {
      font-family: "YS";
      background-image: url("${data.url}");
      margin: 0;
      padding: 20px;
    }

    h1 {
      text-align: center;
      color: #333;
      margin-bottom: 40px;
    }

    .category {
      margin-bottom: 30px;
      background: white;
      border-radius: 10px;
      box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
      padding: 20px;
    }

    .category h2 {
      margin-top: 0;
      color: #2c3e50;
      border-left: 5px solid #3498db;
      padding-left: 10px;
      font-size: 20px;
    }

    .names {
      display: flex;
      flex-wrap: wrap;
      gap: 10px;
      margin-top: 10px;
    }

    .name {
      background: #3498db;
      color: white;
      padding: 5px 12px;
      border-radius: 20px;
      font-size: 14px;
      transition: background 0.3s;
    }

    .name:hover {
      background: #2980b9;
    }
  </style>
</head>
<body>
  <h1>角色语音分类列表</h1>
  <div id="content"></div>
<script id="logData" type="application/json">
  ${JSON.stringify(data.list).replace(/</g, "\\u003c")}
</script>

  <script>
    const logData = JSON.parse(document.getElementById('logData').textContent);
    const contentDiv = document.getElementById('content');
    for (const [category, characters] of Object.entries(logData)) {
      const categoryDiv = document.createElement('div');
      categoryDiv.className = 'category';
      const title = document.createElement('h2');
      title.textContent = category;
      categoryDiv.appendChild(title);
      const namesContainer = document.createElement('div');
      namesContainer.className = 'names';
      characters.forEach(item => {
        item.names.forEach(name => {
          const nameDiv = document.createElement('div');
          nameDiv.className = 'name';
          nameDiv.textContent = name;
          namesContainer.appendChild(nameDiv);
        });
      });
      categoryDiv.appendChild(namesContainer);
      contentDiv.appendChild(categoryDiv);
    }
  </script>
</body>
</html>

`
}
